package com.gitee.wsl.ext.list

import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

/**
 * Copied from [androidx](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:text/text/src/main/java/androidx/compose/ui/text/android/TempListUtils.kt;l=33;drc=b2e3d878411b7fb1147455b1a204cddb7bee1a1b).
 */
@OptIn(ExperimentalContracts::class)
internal inline fun <T> List<T>.fastForEach(action: (T) -> Unit) {
    contract { callsInPlace(action) }
    for (index in indices) {
        val item = get(index)
        action(item)
    }
}

inline fun <T> List<T>.forEachReversed(action: (T) -> Unit): Unit {
    for (i in lastIndex downTo 0) {
        action(this[i])
    }
}

inline fun <T> List<T>.forEachIndexedReversed(action: (index:Int,T) -> Unit): Unit {
    for (i in lastIndex downTo 0) {
        action(i,this[i])
    }
}

@OptIn(ExperimentalContracts::class)
inline fun <T> List<T>.fastForEachIndexed(action: (index: Int, T) -> Unit) {
    contract { callsInPlace(action) }
    for (index in indices) {
        val item = get(index)
        action(index, item)
    }
}

/**
 * Copied from [androidx](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:text/text/src/main/java/androidx/compose/ui/text/android/TempListUtils.kt;l=50;drc=b2e3d878411b7fb1147455b1a204cddb7bee1a1b).
 */
@OptIn(ExperimentalContracts::class)
internal inline fun <T, R> List<T>.fastMap(
    transform: (T) -> R,
): List<R> {
    contract { callsInPlace(transform) }
    val destination = ArrayList<R>(/* initialCapacity = */ size)
    fastForEach { item ->
        destination.add(transform(item))
    }
    return destination
}

/**
 * Returns `true` if at least one element matches the given [predicate].
 *
 * **Do not use for collections that come from public APIs**, since they may not support random
 * access in an efficient way, and this method may actually be a lot slower. Only use for
 * collections that are created by code we control and are known to support random access.
 */
@OptIn(ExperimentalContracts::class)
@Suppress("BanInlineOptIn")
internal inline fun <T> List<T>.fastAny(predicate: (T) -> Boolean): Boolean {
    contract { callsInPlace(predicate) }
    fastForEach { if (predicate(it)) return true }
    return false
}


inline fun <T> List<T>.fastForEachReverse(callback: (T) -> Unit) {
    var n = 0
    while (n < size) {
        callback(this[size - n - 1])
        n++
    }
}

inline fun <T> MutableList<T>.fastIterateRemove(callback: (T) -> Boolean): MutableList<T> {
    var n = 0
    var m = 0
    while (n < size) {
        if (m >= 0 && m != n) this[m] = this[n]
        if (callback(this[n])) m--
        n++
        m++
    }
    while (this.size > m) this.removeAt(this.size - 1)
    return this
}
